﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsycServer
{
    public partial class AsyUdpServer
    {
        /// <summary>
        /// ping标记
        /// </summary>
		public static byte pingByte = byte.MaxValue;

        private static int upByteBuffer;
        private static int downByteBuffer;
        private static int upByteTotal;
        private static int downByteTotal;
        
		public static int UpBytes
		{
			get
			{
				int n = upByteBuffer;
				upByteBuffer = 0;

				return n;
			}
		}

		public static int DownBytes
		{
			get
			{
				int n = downByteBuffer;
				downByteBuffer = 0;

				return n;
			}
		}

		public static int UpBytesTotal
		{
			get
			{
				return upByteTotal;
			}
		}

		public static int DownBytesTotal
		{
			get
			{
				return downByteTotal;
			}
		}
        
        int nmbrOfClients = 0;

        private List<MessageInfo> inMessages = new List<MessageInfo>();
        private List<MessageInfo> outMessages = new List<MessageInfo>();
        private List<MessageInfo> inMessagesExternal = new List<MessageInfo>();
        
        /// <summary>
        /// 请求加入线程
        /// </summary>
        private Thread acceptThread;
        
        /// <summary>
        /// 接收数据线程
        /// </summary>
        private Thread receiveThread;
        
        /// <summary>
        /// 发送数据线程
        /// </summary>
        private Thread sendThread;

        public bool Active
        {
            get
            {
                return udpSocket != null && tcpSocket != null;
            }
        }
        
        /// <summary>
        /// 每10ms执行一次更新，队列结构的数据
        /// </summary>
        public void Update()
        {
            while (inMessages.Count > 0)
            {
                OnMessage(GetClient(inMessages[0].Adress), inMessages[0].Message);
                inMessages.RemoveAt(0);
            }

            while (inMessagesExternal.Count > 0)
            {
                OnMessageExternal(inMessagesExternal[0].Adress, inMessagesExternal[0].Message);
                inMessagesExternal.RemoveAt(0);
            }

            while (connectedList.Count > 0)
            {
                OnConnect(connectedList[0]);
                connectedList.RemoveAt(0);
            }

            while (disconnectedList.Count > 0)
            {
                OnDisconnect(disconnectedList[0]);
                disconnectedList.RemoveAt(0);
            }

            while (debugMessageList.Count > 0)
            {
                OnDebug(debugMessageList[0]);
                debugMessageList.RemoveAt(0);
            }
        }

        
        

        
        public void ClientDisconnected(Client c)
        {
            clientList.Remove(c);
            disconnectedList.Add(c);
        }

        public void Send(MessageBuffer msg, int id) { Send(msg, GetClient(id)); }
        public void Send(MessageBuffer msg, Client c)
        {
            if (c != null && c.udpAdress != null)
                outMessages.Add(new MessageInfo(msg, c.udpAdress, this));
        }

        public void SendExternal(MessageBuffer msg, IPEndPoint ip)
        {
            outMessages.Add(new MessageInfo(msg, ip, this));
        }

        /// <summary>
        /// 服务器关闭
        /// </summary>
        public void Close()
        {
            if (tcpSocket == null || udpSocket == null) return;

            tcpSocket.Stop();
            udpSocket.Close();

            tcpSocket = null;
            udpSocket = null;

            acceptThread.Abort();
            sendThread.Abort();
            receiveThread.Abort();

            acceptThread = null;
            sendThread = null;
            receiveThread = null;

            List<Client> list = new List<Client>();
            list.AddRange(clientList);

            foreach (Client c in list) c.Disconnect();
        }

        public void CatchException(Exception e)
        {
            if (OnException != null) OnException(e);
        }

        public void PingResult(Client c, int millis)
        {
            if (OnPing != null) OnPing(c, millis);
        }
    }
}
